<!DOCTYPE html>  
<html>  
  <head>  
    <title>Custom Animation</title>  
    <link rel="stylesheet" href="https://openlayers.org/en/v4.2.0/css/ol.css" type="text/css">  
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->  
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>  
    <script src="https://openlayers.org/en/v4.2.0/build/ol.js"></script>  
  </head>  
  <body>  
    <div id="map" class="map"></div>  
    <script>  
      var map = new ol.Map({  
        layers: [  
          new ol.layer.Tile({  
            source: new ol.source.OSM({  
              wrapX: false  
            })  
          })  
        ],  
        controls: ol.control.defaults({  
          attributionOptions: /** @type {olx.control.AttributionOptions} */ ({  
            collapsible: false  
          })  
        }),  
        target: 'map',  
        view: new ol.View({  
          center: [0, 0],  
          zoom: 1  
        })  
      });  
  
      var source = new ol.source.Vector({  
        wrapX: false  
      });  
      var vector = new ol.layer.Vector({  
        source: source  
      });  
      map.addLayer(vector);  
  
      // 随机产生一个点并添加到矢量数据源中  
      function addRandomFeature() {  
        var x = Math.random() * 360 - 180;  
        var y = Math.random() * 180 - 90;  
        var geom = new ol.geom.Point(ol.proj.transform([x, y],  
            'EPSG:4326', 'EPSG:3857'));  
        var feature = new ol.Feature(geom);  
        source.addFeature(feature);  
      }  
  
      // 动画持续时间  
      var duration = 3000;  
      // 闪烁动画  
      function flash(feature) {  
        var start = new Date().getTime();  
        var listenerKey;  
        // 执行动画  
        function animate(event) {  
          var vectorContext = event.vectorContext;  
          var frameState = event.frameState;  
          var flashGeom = feature.getGeometry().clone();  
          var elapsed = frameState.time - start;  
          var elapsedRatio = elapsed / duration;  
          // radius will be 5 at start and 30 at end.  
         // 半径从5开始到30结束  
          var radius = ol.easing.easeOut(elapsedRatio) * 25 + 5;  
          var opacity = ol.easing.easeOut(1 - elapsedRatio);  
          // 点样式  
          var style = new ol.style.Style({  
            image: new ol.style.Circle({  
              radius: radius,  
              snapToPixel: false,  
              stroke: new ol.style.Stroke({  
                color: 'rgba(255, 0, 0, ' + opacity + ')',  
                width: 0.25 + opacity  
              })  
            })  
          });  
  
          vectorContext.setStyle(style);  
          vectorContext.drawGeometry(flashGeom);  
          if (elapsed > duration) {  
            ol.Observable.unByKey(listenerKey);  
            return;  
          }  
          // tell OpenLayers to continue postcompose animation  
          // 告诉Openlayers继续postcompose动画  
          map.render();  
        }  
        listenerKey = map.on('postcompose', animate);  
      }  
  
      // 添加要素的时候执行闪烁动画  
      source.on('addfeature', function(e) {  
        flash(e.feature);  
      });  
  
      // 每隔一秒随机创建一个点  
      window.setInterval(addRandomFeature, 1000);  
    </script>  
  </body>  
</html>  
